package com.zx.system.block.service.impl;

import com.zx.core.constant.CacheConstants;
import com.zx.core.context.TenantContextHolder;
import com.zx.core.enums.StatusEnum;
import com.zx.core.page.PageInfo;
import com.zx.core.wrapper.ListWrapper;
import com.zx.core.wrapper.PageWrapper;
import com.zx.core.wrapper.ResponseWrapper;
import com.zx.feign.client.dto.DictTypeDTO;
import com.zx.redis.block.service.RedisBlockService;
import com.zx.security.block.uitls.SecurityUtils;
import com.zx.system.block.dao.SysDictTypeMapper;
import com.zx.system.block.event.DictTypeChangeEvent;
import com.zx.system.block.mapstruct.DictTypeMapStructMapper;
import com.zx.system.block.model.SysDictType;
import com.zx.system.block.param.DictTypeParam;
import com.zx.system.block.service.ISysDictTypeService;
import com.zx.system.block.utils.SystemNoUtils;
import com.zx.system.block.vo.SysDictTypeVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * description: 业务层字典类型服务实现 <br>
 * create: 2025-11-18
 * </p>
 *
 * @author zhou xun
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysDictTypeServiceImpl implements ISysDictTypeService {
    private final SysDictTypeMapper sysDictTypeMapper;
    private final RedisBlockService redisBlockService;
    private final ApplicationEventPublisher eventPublisher;

    /**
     * 获取字典类型信息Map 用于字典类型信息匹配
     *
     * @return 包含字典类型标识符作为键, {@link SysDictType} 对象作为值的映射表{@code Map<String, SysDictType>}
     * @author zhou xun
     * @since 2025-11-18
     */
    @Override
    public Map<String, SysDictType> getDictType() {
        List<SysDictType> sysDictTypeList = sysDictTypeMapper.selectDictTypeList(null, null, null, null, null, null);
        return sysDictTypeList.stream().collect(Collectors.toMap(SysDictType::getDictType, dictType -> dictType));
    }

    /**
     * 查询字典类型列表
     *
     * @param dictTypeParam 字典类型参数
     * @return {@link ListWrapper<SysDictType>}
     * @author zhou xun
     * @since 2025-11-18
     */
    @Override
    public ListWrapper<SysDictType> selectDictTypeList(DictTypeParam dictTypeParam) {
        ListWrapper<SysDictType> result = new ListWrapper<>();
        try {
            // 验证字典类型状态
            if (dictTypeParam.getStatus() != null) {
                StatusEnum enumByCode = StatusEnum.getEnumByCode(dictTypeParam.getStatus());
                if (null == enumByCode) {
                    result.fail("传入的字典类型状态错误!");
                    return result;
                }
            }

            List<SysDictType> sysDictTypeList = sysDictTypeMapper.selectDictTypeList(TenantContextHolder.getTenantId(),
                    dictTypeParam.getDictName(),
                    dictTypeParam.getDictType(),
                    dictTypeParam.getStatus(),
                    dictTypeParam.getCreateTimeStart(),
                    dictTypeParam.getCreateTimeEnd());

            if (null != sysDictTypeList && !sysDictTypeList.isEmpty()) {
                result.setData(sysDictTypeList);
            }
        } catch (Exception e) {
            log.error("查询字典类型列表时发生错误", e);
            result.fail("查询字典类型列表时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 分页查询字典类型列表
     *
     * @param dictTypeParam 字典类型参数
     * @return {@link PageWrapper<SysDictType>}
     * @author zhou xun
     * @since 2025-11-18
     */
    @Override
    public PageWrapper<SysDictType> selectDictTypeListByPage(DictTypeParam dictTypeParam) {
        PageWrapper<SysDictType> result = new PageWrapper<>();
        try {
            // 验证字典类型状态
            if (dictTypeParam.getStatus() != null) {
                StatusEnum enumByCode = StatusEnum.getEnumByCode(dictTypeParam.getStatus());
                if (null == enumByCode) {
                    result.fail("传入的字典类型状态错误!");
                    return result;
                }
            }

            PageInfo pageInfo = new PageInfo(dictTypeParam.getPageNum(), dictTypeParam.getPageSize());
            dictTypeParam.setPageNum(pageInfo.getPageNum());
            dictTypeParam.setPageSize(pageInfo.getPageSize());

            Long count = sysDictTypeMapper.getDictTypeListCount(TenantContextHolder.getTenantId(),
                    dictTypeParam.getDictName(),
                    dictTypeParam.getDictType(),
                    dictTypeParam.getStatus(),
                    dictTypeParam.getCreateTimeStart(),
                    dictTypeParam.getCreateTimeEnd());

            if (count > 0) {
                List<SysDictType> sysDictTypeList = sysDictTypeMapper.getDictTypeListByPage(TenantContextHolder.getTenantId(),
                        dictTypeParam.getDictName(),
                        dictTypeParam.getDictType(),
                        dictTypeParam.getStatus(),
                        dictTypeParam.getCreateTimeStart(),
                        dictTypeParam.getCreateTimeEnd(),
                        dictTypeParam.getPageNum(),
                        dictTypeParam.getPageSize());

                result.setData(sysDictTypeList);
            }
            result.setTotal(count);
            result.setCurrentPageNum(dictTypeParam.getPageNum());
            result.setTotalPage(pageInfo);
        } catch (Exception e) {
            log.error("分页查询字典类型列表时发生错误", e);
            result.fail("分页查询字典类型列表时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 查询字典类型列表VO
     *
     * @param dictTypeParam 字典类型参数
     * @return {@link ListWrapper<SysDictTypeVO>}
     * @author zhou xun
     * @since 2025-11-18
     */
    @Override
    public ListWrapper<SysDictTypeVO> selectDictTypeVOList(DictTypeParam dictTypeParam) {
        ListWrapper<SysDictTypeVO> result = new ListWrapper<>();
        // 获取字典类型列表
        ListWrapper<SysDictType> listWrapper = selectDictTypeList(dictTypeParam);

        // 验证请求是否成功或数据是否为空
        if (listWrapper.verifyFail()) {
            result.fail(listWrapper.getMsg());
            return result;
        }

        if (null != listWrapper.getData() && !listWrapper.getData().isEmpty()) {
            // 转换并处理数据
            List<SysDictTypeVO> processedData = listWrapper.getData().stream()
                    .map(DictTypeMapStructMapper.INSTANCE::sysDictTypeToSysDictTypeVO)
                    .collect(Collectors.toList());

            result.setData(processedData);
        }
        return result;
    }

    /**
     * 分页查询字典类型列表VO
     *
     * @param dictTypeParam 字典类型参数
     * @return {@link PageWrapper<SysDictTypeVO>}
     * @author zhou xun
     * @since 2025-11-18
     */
    @Override
    public PageWrapper<SysDictTypeVO> selectDictTypeVOListByPage(DictTypeParam dictTypeParam) {
        PageWrapper<SysDictTypeVO> result = new PageWrapper<>();
        // 获取字典类型列表
        PageWrapper<SysDictType> pageWrapper = selectDictTypeListByPage(dictTypeParam);

        // 验证请求是否成功或数据是否为空
        if (pageWrapper.verifyFail()) {
            result.fail(pageWrapper.getMsg());
            return result;
        }

        if (null != pageWrapper.getData() && !pageWrapper.getData().isEmpty()) {
            // 转换并处理数据
            List<SysDictTypeVO> processedData = pageWrapper.getData().stream()
                    .map(DictTypeMapStructMapper.INSTANCE::sysDictTypeToSysDictTypeVO)
                    .collect(Collectors.toList());
            result.setData(processedData);

        }
        result.setTotal(pageWrapper.getTotal());
        result.setCurrentPageNum(pageWrapper.getCurrentPageNum());
        return result;
    }

    /**
     * 新增字典类型
     *
     * @param dictTypeParam 字典类型参数
     * @return {@link ResponseWrapper}
     * @author zhou xun
     * @since 2025-11-18
     */
    @Override
    public ResponseWrapper addDictType(DictTypeParam dictTypeParam) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证字典类型状态
            StatusEnum statusEnum = StatusEnum.getEnumByCode(dictTypeParam.getStatus());
            if (null == statusEnum) {
                result.fail("传入的字典类型状态错误!");
                return result;
            }

            SysDictType sysDictType = DictTypeMapStructMapper.INSTANCE.dictTypeParamToSysDictType(dictTypeParam);
            // 设置id
            sysDictType.setId(SystemNoUtils.generateSystemId());
            sysDictType.setCreateBy(SecurityUtils.getUserId());
            sysDictType.setCreateTime(LocalDateTime.now());
            sysDictTypeMapper.insert(sysDictType);

            // 发布字典类型变更事件
            DictTypeChangeEvent event = new DictTypeChangeEvent(this, dictTypeParam.getDictType(), "ADD");
            eventPublisher.publishEvent(event);
        } catch (Exception e) {
            log.error("新增字典类型时发生错误", e);
            result.fail("新增字典类型时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 编辑字典类型
     *
     * @param dictTypeParam 字典类型参数
     * @return {@link ResponseWrapper}
     * @author zhou xun
     * @since 2025-11-18
     */
    @Override
    public ResponseWrapper editDictType(DictTypeParam dictTypeParam) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证字典类型状态
            StatusEnum statusEnum = StatusEnum.getEnumByCode(dictTypeParam.getStatus());
            if (null == statusEnum) {
                result.fail("传入的字典类型状态错误!");
                return result;
            }

            // 检查字典类型是否存在
            SysDictType existingDictType = sysDictTypeMapper.selectByPrimaryKey(dictTypeParam.getId());
            if (existingDictType == null) {
                result.fail("字典类型不存在!");
                return result;
            }

            SysDictType sysDictType = DictTypeMapStructMapper.INSTANCE.dictTypeParamToSysDictType(dictTypeParam);
            sysDictType.setUpdateBy(SecurityUtils.getUserId());
            sysDictType.setUpdateTime(LocalDateTime.now());
            sysDictTypeMapper.updateByPrimaryKeySelective(sysDictType);

            // 发布字典类型变更事件
            DictTypeChangeEvent event = new DictTypeChangeEvent(this, dictTypeParam.getDictType(), "UPDATE");
            eventPublisher.publishEvent(event);
        } catch (Exception e) {
            log.error("编辑字典类型时发生错误", e);
            result.fail("编辑字典类型时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 编辑字典类型状态
     *
     * @param id     字典类型Id
     * @param status 字典类型状态 0停用 1 启用
     * @return {@link ResponseWrapper}
     * @author zhou xun
     * @since 2025-11-18
     */
    @Override
    public ResponseWrapper editDictTypeStatus(String id, Integer status) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证字典类型状态
            StatusEnum statusEnum = StatusEnum.getEnumByCode(status);
            if (null == statusEnum) {
                result.fail("传入的字典类型状态错误!");
                return result;
            }

            // 验证字典类型是否存在
            SysDictType selectByPrimaryKey = sysDictTypeMapper.selectByPrimaryKey(id);
            if (null == selectByPrimaryKey) {
                result.fail("传入的字典类型信息不存在!");
                return result;
            }

            SysDictType sysDictType = new SysDictType();
            sysDictType.setId(id);
            sysDictType.setStatus(status);
            sysDictType.setUpdateBy(SecurityUtils.getUserId());
            sysDictType.setUpdateTime(LocalDateTime.now());
            sysDictTypeMapper.updateByPrimaryKeySelective(sysDictType);

            // 发布字典类型变更事件
            DictTypeChangeEvent event = new DictTypeChangeEvent(this, selectByPrimaryKey.getDictType(), "UPDATE");
            eventPublisher.publishEvent(event);
        } catch (Exception e) {
            log.error("编辑字典类型状态时发生错误", e);
            result.fail("编辑字典类型状态时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 删除字典类型
     *
     * @param dictTypeId 字典类型Id
     * @return {@link ResponseWrapper}
     * @author zhou xun
     * @since 2025-11-18
     */
    @Override
    public ResponseWrapper deleteDictType(String dictTypeId) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证字典类型是否存在
            SysDictType selectByPrimaryKey = sysDictTypeMapper.selectByPrimaryKey(dictTypeId);
            if (null == selectByPrimaryKey) {
                result.fail("传入的字典类型信息不存在!");
                return result;
            }

            sysDictTypeMapper.deleteByPrimaryKey(dictTypeId);

            // 发布字典类型变更事件
            DictTypeChangeEvent event = new DictTypeChangeEvent(this, selectByPrimaryKey.getDictType(), "DELETE");
            eventPublisher.publishEvent(event);
        } catch (Exception e) {
            log.error("删除字典类型时发生错误", e);
            result.fail("删除字典类型时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 查询启用的字典类型列表VO
     *
     * @return {@link ListWrapper<SysDictTypeVO>}
     * @author zhou xun
     * @since 2025-11-19
     */
    @Override
    public ListWrapper<SysDictTypeVO> selectEnableDictTypeVOList() {
        ListWrapper<SysDictTypeVO> result = new ListWrapper<>();
        try {
            // 先从VO Redis缓存中获取
            String voCacheKey = CacheConstants.DICT_TYPE_KEY + "enable_list";
            List<SysDictTypeVO> cachedVOData = redisBlockService.getCachedObject(voCacheKey, List.class);
            if (cachedVOData != null) {
                log.debug("从VO缓存获取字典类型列表，缓存键: {}", voCacheKey);
                result.setData(cachedVOData);
                return result;
            }

            // 尝试从共享基础数据缓存获取
            String baseCacheKey = CacheConstants.DICT_TYPE_KEY + "base_enable_list";
            List<SysDictType> cachedBaseData = redisBlockService.getCachedObject(baseCacheKey, List.class);
            if (cachedBaseData != null) {
                List<SysDictTypeVO> dictTypeVOList = cachedBaseData.stream()
                        .map(DictTypeMapStructMapper.INSTANCE::sysDictTypeToSysDictTypeVO)
                        .collect(Collectors.toList());
                result.setData(dictTypeVOList);

                // 存入VO缓存
                redisBlockService.setCacheObject(voCacheKey, dictTypeVOList, CacheConstants.DEFAULT_EXPIRE_MINUTES, CacheConstants.DEFAULT_EXPIRE_TIME_UNIT);
                return result;
            }

            List<SysDictType> dictTypeList = sysDictTypeMapper.selectDictTypeList(null, null, null, StatusEnum.ENABLE.getCode(), null, null);
            if (dictTypeList != null && !dictTypeList.isEmpty()) {
                List<SysDictTypeVO> dictTypeVOList = dictTypeList.stream()
                        .map(DictTypeMapStructMapper.INSTANCE::sysDictTypeToSysDictTypeVO)
                        .collect(Collectors.toList());
                result.setData(dictTypeVOList);

                // 存入Redis缓存，设置过期时间30分钟
                redisBlockService.setCacheObject(voCacheKey, dictTypeVOList, CacheConstants.DEFAULT_EXPIRE_MINUTES, CacheConstants.DEFAULT_EXPIRE_TIME_UNIT);
                // 同时存入共享基础数据缓存
                redisBlockService.setCacheObject(baseCacheKey, dictTypeList, CacheConstants.DEFAULT_EXPIRE_MINUTES, CacheConstants.DEFAULT_EXPIRE_TIME_UNIT);
                log.debug("字典类型列表存入缓存，缓存键: {}", voCacheKey);
            }
        } catch (Exception e) {
            log.error("查询启用的字典类型列表VO时发生错误", e);
            result.fail("查询字典类型失败: " + e.getMessage());
        }
        return result;
    }

    /**
     * 获取启用的字典类型列表DTO
     *
     * @return {@link ListWrapper< DictTypeDTO >}
     * @author zhou xun
     * @since 2025-11-21
     */
    @Override
    public ListWrapper<DictTypeDTO> selectEnableDictTypeDTOList() {
        ListWrapper<DictTypeDTO> result = new ListWrapper<>();
        try {
            // 先从DTO Redis缓存中获取
            String dtoCacheKey = CacheConstants.DICT_TYPE_KEY + "enable_list_dto";
            List<DictTypeDTO> cachedDTOData = redisBlockService.getCachedObject(dtoCacheKey, List.class);
            if (cachedDTOData != null) {
                log.debug("从DTO缓存获取字典类型列表，缓存键: {}", dtoCacheKey);
                result.setData(cachedDTOData);
                return result;
            }

            // 尝试从共享基础数据缓存获取
            String baseCacheKey = CacheConstants.DICT_TYPE_KEY + "base_enable_list";
            List<SysDictType> cachedBaseData = redisBlockService.getCachedObject(baseCacheKey, List.class);
            if (cachedBaseData != null) {
                List<DictTypeDTO> dictTypeDTOList = cachedBaseData.stream()
                        .map(DictTypeMapStructMapper.INSTANCE::sysDictTypeToDictTypeDTO)
                        .collect(Collectors.toList());
                result.setData(dictTypeDTOList);

                // 存入DTO缓存
                redisBlockService.setCacheObject(dtoCacheKey, dictTypeDTOList, CacheConstants.DEFAULT_EXPIRE_MINUTES, CacheConstants.DEFAULT_EXPIRE_TIME_UNIT);
                return result;
            }

            List<SysDictType> dictTypeList = sysDictTypeMapper.selectDictTypeList(null,
                    null, null, StatusEnum.ENABLE.getCode(), null, null);
            if (dictTypeList != null && !dictTypeList.isEmpty()) {
                List<DictTypeDTO> dictTypeDTOList = dictTypeList.stream()
                        .map(DictTypeMapStructMapper.INSTANCE::sysDictTypeToDictTypeDTO)
                        .collect(Collectors.toList());
                result.setData(dictTypeDTOList);

                // 存入Redis缓存，设置过期时间30分钟
                redisBlockService.setCacheObject(dtoCacheKey, dictTypeDTOList, CacheConstants.DEFAULT_EXPIRE_MINUTES, CacheConstants.DEFAULT_EXPIRE_TIME_UNIT);
                // 同时存入共享基础数据缓存
                redisBlockService.setCacheObject(baseCacheKey, dictTypeList, CacheConstants.DEFAULT_EXPIRE_MINUTES, CacheConstants.DEFAULT_EXPIRE_TIME_UNIT);
                log.debug("字典类型列表DTO存入缓存，缓存键: {}", dtoCacheKey);
            }
        } catch (Exception e) {
            log.error("查询启用的字典类型列表DTO时发生错误", e);
            result.fail("查询字典类型失败: " + e.getMessage());
        }
        return result;
    }
}